package zdh.avatar.softphone;

import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.sourceforge.peers.Logger;
import net.sourceforge.peers.gui.CallFrame;
import net.sourceforge.peers.gui.EventManager;
import net.sourceforge.peers.gui.Registration;
import net.sourceforge.peers.sip.RFC3261;
import net.sourceforge.peers.sip.Utils;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldName;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldValue;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaders;
import net.sourceforge.peers.sip.syntaxencoding.SipUriSyntaxException;
import net.sourceforge.peers.sip.transport.SipRequest;
import net.sourceforge.peers.sip.transport.SipResponse;
import zdh.avatar.gui.MainFrame;

/**
 * TODO: Call is limited only. fix buttons. cant answer.
 *
 * @author Gem Seeker
 */
public class Softphone extends JPanel {

    public static final String ANSWER_COMMAND = "answer";
    public static final String CALL_COMMAND = "call";
    public static final String HANGUP_COMMAND = "hangup";
    public static final String BUSY_COMMAND = "busyhere";

    public EventManager eventManager;

    private Registration registration;
    private Logger logger;
    private CallFrame callFrame;
    private SipRequest sipRequest;
    private SipResponse sipResponse;

    private MainFrame main;

    public Softphone(MainFrame main) {
        initComponents();
        loadAllContact();
        String peersHome = Utils.DEFAULT_PEERS_HOME;
        logger = new Logger(peersHome);
        this.main = main;

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                String peersHome = Utils.DEFAULT_PEERS_HOME;
                registration = new Registration(lbl_reg, logger);
                eventManager = new EventManager(Softphone.this,
                        peersHome, logger);
                try {
                    eventManager.register();
                } catch (SipUriSyntaxException e) {
                    lbl_stat.setText(e.getMessage());
                }
            }
        });
        thread.start();

        try {
            while (eventManager == null) {
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            return;
        }

        callFrame = new CallFrame(Softphone.this, "", "", eventManager, logger);
        btn_register.setActionCommand(EventManager.ACTION_ACCOUNT);
        btn_register.addActionListener(eventManager);
        btn_call.setActionCommand(CALL_COMMAND);
        btn_hangup.setActionCommand(HANGUP_COMMAND);
    }

    private void loadAllContact() {
        JLabel jLabel = new JLabel();
        jLabel.setText("Tien");
        jLabel.setLocation(50, 50);
        jLabel.setVisible(true);
        this.add(jLabel);
        pnl_contacts.add(jLabel);
        jLabel.setVisible(true);
        pnl_contacts.setVisible(true);
    }

    public void registerFailed(SipResponse sipResponse) {
        registration.registerFailed();
    }

    public void registerSuccessful(SipResponse sipResponse) {
        registration.registerSuccessful();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                lbl_username.setText(eventManager.userAgent.getUserpart().toUpperCase());
                URL url = getClass().getResource("blue-icon.png");
                ImageIcon i = new ImageIcon(url);
                icon.setIcon(i);
            }
        });
    }

    public void registering(SipRequest sipRequest) {
        registration.registerSent();
    }

    public void callClicked() {
        // TODO: display the status calling and whom we are caling
        callFrame.callClicked();
//	String to = tf_uri.getName();
//	callClickedState(to);
    }

    public void incomingCall() {
        callFrame.incomingCall();
//	incomingCallState(fromValue);
    }

    public void remoteHangup() {
        callFrame.remoteHangup();
    }

    public void error(SipResponse sipResponse) {
        callFrame.error(sipResponse);
    }

    public void calleePickup() {
        callFrame.calleePickup();
    }

    public void ringing() {
        callFrame.ringing();
    }

    public void setSipRequest(SipRequest sipRequest) {
        this.sipRequest = sipRequest;
        callFrame.setSipRequest(sipRequest);
    }

    // misc.
    public void setLabelText(String text) {
        lbl_stat.setText(text);
    }

    public void socketExceptionOnStartup() {
        JOptionPane.showMessageDialog(this, "peers SIP port "
                + "unavailable, exiting");
        System.exit(1);
    }

    // States
    public void incomingCallState() {
        SipHeaders sipHeaders = sipRequest.getSipHeaders();
        SipHeaderFieldName sipHeaderFieldName
                = new SipHeaderFieldName(RFC3261.HDR_FROM);
        SipHeaderFieldValue from = sipHeaders.get(sipHeaderFieldName);
        final String fromValue = from.getValue();

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                btn_call.setText("Answer");
                btn_hangup.setEnabled(false);
                lbl_stat.setText("Incoming call: " + fromValue);
            }
        });
    }

    public void callClickedState() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                btn_call.setEnabled(false);
                String to = tf_uri.getText();
                lbl_stat.setText("Calling " + to);
            }
        });
    }

    public void remoteHangupState() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                lbl_stat.setText("Remote Hangup");
            }
        });
        terminatedState();
    }

    public void ringingState() {
        // TODO: play a ringing tone
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                lbl_stat.setText("Ringing...");
            }
        });
    }

    public void successState() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                btn_hangup.setEnabled(true);
                btn_busy.setEnabled(false);
                lbl_stat.setText("Call on Session...");
            }
        });
    }

    public void failedState() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                lbl_stat.setText("Failed");
            }
        });
        terminatedState();
    }

    public void terminatedState() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                btn_call.setEnabled(true);
                btn_hangup.setEnabled(true);
                btn_busy.setEnabled(true);
                btn_call.setText("Call");
                lbl_stat.setText("No Incoming Call");
                callFrame = new CallFrame(Softphone.this, "", "", eventManager, logger);
            }
        });
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSeparator1 = new javax.swing.JSeparator();
        jToolBar2 = new javax.swing.JToolBar();
        cb_sip = new javax.swing.JComboBox();
        tf_uri = new javax.swing.JTextField();
        lbl_username = new javax.swing.JLabel();
        jSeparator2 = new javax.swing.JSeparator();
        lbl_stat = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        btn_call = new javax.swing.JButton();
        btn_hangup = new javax.swing.JButton();
        btn_busy = new javax.swing.JButton();
        jToolBar3 = new javax.swing.JToolBar();
        btn_contacts = new javax.swing.JButton();
        jSeparator3 = new javax.swing.JSeparator();
        pnl_contacts = new javax.swing.JPanel();
        btn_register = new javax.swing.JButton();
        lbl_reg = new javax.swing.JLabel();
        icon = new javax.swing.JLabel();

        setBorder(javax.swing.BorderFactory.createEtchedBorder());
        setMaximumSize(new java.awt.Dimension(300, 400));
        setMinimumSize(new java.awt.Dimension(300, 400));

        jToolBar2.setFloatable(false);
        jToolBar2.setRollover(true);

        cb_sip.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "SIP", "TEL" }));
        cb_sip.setEnabled(false);
        jToolBar2.add(cb_sip);

        tf_uri.setForeground(new java.awt.Color(102, 102, 102));
        tf_uri.setText("SIP URI here");
        tf_uri.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tf_uriMouseClicked(evt);
            }
        });
        jToolBar2.add(tf_uri);

        lbl_username.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
        lbl_username.setForeground(new java.awt.Color(102, 102, 102));
        lbl_username.setText("USER NAME");

        lbl_stat.setForeground(new java.awt.Color(153, 153, 153));
        lbl_stat.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lbl_stat.setText("Call status...");

        jPanel1.setLayout(new java.awt.GridLayout(1, 0));

        btn_call.setText("Call");
        btn_call.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_callActionPerformed(evt);
            }
        });
        jPanel1.add(btn_call);

        btn_hangup.setText("Hangup");
        btn_hangup.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_hangupActionPerformed(evt);
            }
        });
        jPanel1.add(btn_hangup);

        btn_busy.setText("Busy");
        btn_busy.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_busyActionPerformed(evt);
            }
        });
        jPanel1.add(btn_busy);

        jToolBar3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jToolBar3.setFloatable(false);
        jToolBar3.setRollover(true);

        btn_contacts.setFont(new java.awt.Font("Tahoma", 2, 11)); // NOI18N
        btn_contacts.setForeground(new java.awt.Color(153, 153, 153));
        btn_contacts.setText("Show Contacts");
        btn_contacts.setFocusable(false);
        btn_contacts.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btn_contacts.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar3.add(btn_contacts);

        javax.swing.GroupLayout pnl_contactsLayout = new javax.swing.GroupLayout(pnl_contacts);
        pnl_contacts.setLayout(pnl_contactsLayout);
        pnl_contactsLayout.setHorizontalGroup(
            pnl_contactsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        pnl_contactsLayout.setVerticalGroup(
            pnl_contactsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 135, Short.MAX_VALUE)
        );

        btn_register.setText("Register");
        btn_register.setFocusable(false);
        btn_register.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btn_register.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);

        lbl_reg.setText("Registration");

        icon.setIcon(new javax.swing.ImageIcon(getClass().getResource("/zdh/avatar/softphone/red-icon.png"))); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSeparator1)
            .addComponent(jSeparator2)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbl_stat, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(lbl_reg, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(btn_register)
                                .addGap(0, 0, Short.MAX_VALUE))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(icon)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(lbl_username, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                            .addComponent(pnl_contacts, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jToolBar3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jSeparator3))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbl_username, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(icon))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lbl_stat, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnl_contacts, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(btn_register)
                    .addComponent(lbl_reg, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    // GUI Actions
    private void btn_callActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_callActionPerformed
        System.out.println(btn_call.getActionCommand());
        if (callFrame.state == callFrame.UAS) {
            callFrame._pickup();
        } else {
            if (!tf_uri.getText().equalsIgnoreCase("SIP URI here")) {
                String protocol = cb_sip.getSelectedItem().toString().toLowerCase();
                eventManager.callClicked(protocol + ":" + tf_uri.getText());
            }else{
                JOptionPane.showMessageDialog(this, "Invalid SIP URI");
            }
        }
    }//GEN-LAST:event_btn_callActionPerformed

    private void btn_hangupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_hangupActionPerformed
        System.out.println(btn_hangup.getActionCommand());
        if (callFrame.state == callFrame.RINGING
                || callFrame.state == callFrame.UAC
                || callFrame.state == callFrame.SUCCESS) {
            callFrame._hangup();
        }
    }//GEN-LAST:event_btn_hangupActionPerformed

    private void tf_uriMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tf_uriMouseClicked
        tf_uri.selectAll();
    }//GEN-LAST:event_tf_uriMouseClicked

    private void btn_busyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_busyActionPerformed
        if (callFrame.state == callFrame.UAS) {
            callFrame._busyHere();
        }
    }//GEN-LAST:event_btn_busyActionPerformed
    //<editor-fold defaultstate="collapsed" desc="Component declarations">
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btn_busy;
    private javax.swing.JButton btn_call;
    private javax.swing.JButton btn_contacts;
    private javax.swing.JButton btn_hangup;
    private javax.swing.JButton btn_register;
    private javax.swing.JComboBox cb_sip;
    private javax.swing.JLabel icon;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JSeparator jSeparator3;
    private javax.swing.JToolBar jToolBar2;
    private javax.swing.JToolBar jToolBar3;
    private javax.swing.JLabel lbl_reg;
    private javax.swing.JLabel lbl_stat;
    private javax.swing.JLabel lbl_username;
    private javax.swing.JPanel pnl_contacts;
    private javax.swing.JTextField tf_uri;
    // End of variables declaration//GEN-END:variables
    //</editor-fold>
}
